﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Zgq.CommonTools
{
    public static class ReflectionHelper
    {
        public static T GetPropertyVal<T>(object dataItem, string propertyName)
        {
            T _t = default(T);
            if (dataItem != null)
            {
                PropertyInfo prop = dataItem.GetType().GetProperty(propertyName);
                if (prop != null)
                {
                    object oVal = prop.GetValue(dataItem, null);
                    Type _tBaseType = GetUnderlyingType(typeof(T));
                    if (oVal != null)
                    {
                        _t = (T)Convert.ChangeType(oVal, _tBaseType, System.Globalization.CultureInfo.InvariantCulture);
                        // _t = (T)oVal;
                    }
                }
            }

            return _t;
        }

        public static void SetPropertyVal(object dataItem, string propertyName, object oVal)
        {
            if (dataItem != null)
            {
                PropertyInfo prop = dataItem.GetType().GetProperty(propertyName);
                if (prop != null)
                {
                    prop.SetValue(dataItem, oVal, null);
                }
            }
        }

        public static Type GetUnderlyingType(Type _type)
        {
            if (_type.IsGenericType && _type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))//判断convertsionType是否为nullable泛型类  
            {
                //如果type为nullable类，声明一个NullableConverter类，该类提供从Nullable类到基础基元类型的转换  
                System.ComponentModel.NullableConverter nullableConverter = new System.ComponentModel.NullableConverter(_type);
                //将type转换为nullable对的基础基元类型  
                _type = nullableConverter.UnderlyingType;
            }
            return _type;
        }

        public static object ChangeType(this object obj, Type _type)
        {
            object _obj = null;
            try
            {
                if (obj != null)
                    return Convert.ChangeType(obj, _type, System.Globalization.CultureInfo.InvariantCulture);
                else
                    _obj = obj;
            }
            catch { }
            return _obj;
        }

        public static void RemoveEvent<T>(T c, string name)
        {
            Delegate[] invokeList = GetObjectEventList(c, name);
            if (invokeList != null)
            {
                var _event = c.GetType().GetEvent(name);
                foreach (Delegate del in invokeList)
                    _event.RemoveEventHandler(c, del);
            }
        }

        ///  <summary>     
        /// 获取对象事件 zgke@sina.com qq:116149     
        ///  </summary>     
        ///  <param name="p_Object">对象 </param>     
        ///  <param name="p_EventName">事件名 </param>     
        ///  <returns>委托列 </returns>     
        public static Delegate[] GetObjectEventList(object p_Object, string p_EventName)
        {
            FieldInfo _Field = p_Object.GetType().GetField(p_EventName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
            if (_Field == null)
            {
                return null;
            }
            object _FieldValue = _Field.GetValue(p_Object);
            if (_FieldValue != null && _FieldValue is Delegate)
            {
                Delegate _ObjectDelegate = (Delegate)_FieldValue;
                return _ObjectDelegate.GetInvocationList();
            }
            return null;
        }


        public static object CallMethod(string fileName, string fullClass, string methodName, params object[] paras)
        {
            string dllFile = string.Format("{0}{1}.dll", System.AppDomain.CurrentDomain.BaseDirectory, fileName);
            if (!System.IO.File.Exists(dllFile)) throw new Exception(string.Format("找不到文件【{0}】！", dllFile));

            var assembly = Assembly.LoadFile(dllFile);

            var type = assembly.GetType(fullClass);
            if (type == null) throw new Exception("在该程序集中不能找到对应的类！");

            var method = type.GetMethod(methodName);

            var ins = Activator.CreateInstance(type);

            return method.Invoke(ins, paras);
        }

        public static object CallMethodByStatic(string fileName, string fullClass, string methodName, params object[] paras)
        {
            string dllFile = string.Format("{0}{1}.dll", System.AppDomain.CurrentDomain.BaseDirectory, fileName);
            if (!System.IO.File.Exists(dllFile)) throw new Exception(string.Format("找不到文件【{0}】！", dllFile));

            var assembly = Assembly.LoadFile(dllFile);

            var type = assembly.GetType(fullClass);
            if (type == null) throw new Exception("在该程序集中不能找到对应的类！");

            return type.InvokeMember(methodName, System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, null, null, paras);
        }
    }
}
